package com.vecspace.utils;


import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.beanutils.BeanMap;

import com.vecspace.data.model.reflect.ReflectUtil;
import com.vecspace.data.numerical.HNumerical;

/**将obj强制转换为指定的类型。
 * 
 * @version: 1.0
 * @author: wanghua
 * @reviewer: 
 */
public class Convert {
	public static int parse(String s,int default_value){
		int num = default_value;
		try{
			num = Integer.valueOf(s);
		}catch(Exception ex){
			
		}
		return num;
	}
	
	public static double parse(String s,double default_value){
		double num = default_value;
		try{
			num = Double.valueOf(s);
		}catch(Exception ex){
			
		}
		return num;
	}
	
	public static float parse(String s,float default_value){
		float num = default_value;
		try{
			num = Float.valueOf(s);
		}catch(Exception ex){
			
		}
		return num;
	}
	
	public static Date parse(String s,Date default_value){
		Date date = default_value;
		try{
			SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			if(s.length() == 10) {
				simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
			}
			date = simpleDateFormat.parse(s);
		}catch(Exception ex){
			
		}
		return date;
	}
	
	public static String toString(Object obj, String defaultvalue) {
		if (obj == null)
			return defaultvalue;
		else {
			 if(obj instanceof String)
				return (String) obj;
			 else{
				return obj.toString();
			}

		}
	}
	 
	public static int toInt(Object obj, int defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		try{
			if(obj instanceof Integer) {
				return (Integer)obj;
			}
			else if(obj instanceof Long) {
				Long d = (Long)obj;
				return d.intValue();
			}else if(obj instanceof Short) {
				Short d = (Short)obj;
				return d.intValue();
			}else if(obj instanceof Byte) {
				Byte d = (Byte)obj;
				return d.intValue();
			}else if(obj instanceof BigDecimal) {
				BigDecimal d = (BigDecimal)obj;
				return d.intValue();
			}else if(obj instanceof Double) {
				Double d = (Double)obj+0.5;
				return d.intValue();
			}else{
				int n = Integer.parseInt(obj.toString());
				return n;
			}
		}catch(Exception e){
			return defaultvalue;
		}
	}
	
	public static Integer toInteger(Object obj, Integer defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		try{
			if(obj instanceof Integer) {
				return (Integer)obj;
			}
			else if(obj instanceof Long) {
				Long d = (Long)obj;
				return d.intValue();
			}else if(obj instanceof Short) {
				Short d = (Short)obj;
				return d.intValue();
			}else if(obj instanceof Byte){
				return ((Byte)obj).intValue();
			}else if(obj instanceof BigDecimal) {
				BigDecimal d = (BigDecimal)obj;
				return d.intValue();
			}else if(obj instanceof Double) {
				Long d = Math.round((Double)obj);
				return d.intValue();
			}else{
				Integer n = Integer.parseInt(obj.toString());
				return n;
			}
		}catch(Exception e){
			return defaultvalue;
		}
	}
	
	public static short toShort(Object obj, short defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		try{
			if(obj instanceof Integer) {
				return ((Integer)obj).shortValue();
			}
			else if(obj instanceof BigDecimal) {
				BigDecimal d = (BigDecimal)obj;
				return d.shortValue();
			}else if(obj instanceof Byte){
				return ((Byte)obj).shortValue();
			}else if(obj instanceof Short){
				return (short)obj;
			}else if(obj instanceof Long){
				return ((Long)obj).shortValue();
			}else if(obj instanceof Double) {
				Double d = (Double)obj+0.5;
				return d.shortValue();
			}else{
				short n = Short.parseShort(obj.toString());
				return n;
			}
		}catch(Exception e){
			return defaultvalue;
		}
	}
	
	/**把字符串转为数字，如果无法转换，则返回默认值。除非defaultvalue为null，否则任何情况下都不会返回null。
	 * 
	 * @param str
	 * @param defaultvalue
	 * @return 
	 * @author  wanghua
	 */
	public static Long toLong(String str, Long defaultvalue){
		if(str==null || str.length() == 0)return defaultvalue;
		Long num;
		try {
			num = Long.parseLong(str);
		}catch(Exception e){
			num = defaultvalue;
		}
		return num;
	}
	
	public static Long toLong(Object obj, Long defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		try{
			if(obj instanceof Long) {
				return (Long)obj;
			}
			else if(obj instanceof Integer) {
				Integer d = (Integer)obj;
				return d.longValue();
			}else if(obj instanceof Short) {
				Short d = (Short)obj;
				return d.longValue();
			}else if(obj instanceof Byte){
				return ((Byte)obj).longValue();
			}else if(obj instanceof BigDecimal) {
				BigDecimal d = (BigDecimal)obj;
				return d.longValue();
			}else if(obj instanceof Double) {
				Long d = Math.round((Double)obj);
				return d;
			}else{
				Long n = Long.parseLong(obj.toString());
				return n;
			}
		}catch(Exception e){
			return defaultvalue;
		}
	}
	/**
	 * 
	 * @param obj Double,QNumerical, BigDecimal, String, Integer等
	 * @param defaultvalue 转换发生异常时的返回值
	 * @return 
	 * @author: wanghua
	 */
	public static double toDouble(Object obj, double defaultvalue){		
		if(obj == null) {
			return defaultvalue;
		}
		try{
			if(obj instanceof Double) {
				Double d = (Double)obj;
				return d;
			}else if(obj instanceof BigDecimal) {
				BigDecimal d = (BigDecimal)obj;
				return d.doubleValue();
			}else if(obj instanceof HNumerical) {
				HNumerical qnum = (HNumerical)obj;
				BigDecimal decimal = qnum.getValue();
				if(decimal != null)return decimal.doubleValue();
				else return defaultvalue;
			}else if(obj instanceof Integer){
				return ((Integer)obj).doubleValue();
			}else if(obj instanceof Long){
				return ((Long)obj).doubleValue();
			}else if(obj instanceof Short){
				return ((Short)obj).doubleValue();
			}else if(obj instanceof Byte){
				return ((Byte)obj).doubleValue();
			}else {
				double d = Double.parseDouble(obj.toString());
				return d;
			}
		}catch(Exception e){
			return defaultvalue;
		}
	}

	public static Double toDouble(Object obj, Double defaultvalue){		
		if(obj == null) {
			return defaultvalue;
		}
		try{
			if(obj instanceof Double) {
				Double d = (Double)obj;
				return d;
			}else if(obj instanceof BigDecimal) {
				BigDecimal d = (BigDecimal)obj;
				return d.doubleValue();
			}else if(obj instanceof HNumerical) {
				HNumerical qnum = (HNumerical)obj;
				BigDecimal decimal = qnum.getValue();
				if(decimal != null)return decimal.doubleValue();
				else return defaultvalue;
			}else if(obj instanceof Integer){
				return ((Integer)obj).doubleValue();
			}else if(obj instanceof Long){
				return ((Long)obj).doubleValue();
			}else if(obj instanceof Short){
				return ((Short)obj).doubleValue();
			}else if(obj instanceof Byte){
				return ((Byte)obj).doubleValue();
			}else {
				double d = Double.parseDouble(obj.toString());
				return d;
			}
		}catch(Exception e){
			return defaultvalue;
		}
	}
	
	/**
	 * 可以返回null
	 * @param obj
	 * @return 
	 * @author: wanghua
	 */
	public static BigDecimal toBigDecimal(Object obj){		
		if(obj == null) {
			return null;
		}
		try{
			if(obj instanceof Double) {
				Double d = (Double)obj;
				return BigDecimal.valueOf(d.doubleValue());
			}else if(obj instanceof HNumerical) {
				HNumerical qnum = (HNumerical)obj;
				BigDecimal decimal = qnum.getValue();
				return decimal;
			}else if(obj instanceof BigDecimal) {
				BigDecimal d = (BigDecimal)obj;
				return d;
			}else if(obj instanceof Integer){
				Integer n = (Integer)obj;
				return BigDecimal.valueOf(n.longValue());
			}else if(obj instanceof Long){
				Long n = (Long)obj;
				return BigDecimal.valueOf(n.longValue());
			}else if(obj instanceof Short){
				Short n = (Short)obj;
				return BigDecimal.valueOf(n.longValue());
			}else if(obj instanceof Byte){
				Byte n = (Byte)obj;
				return BigDecimal.valueOf(n.longValue());
			}else {
				BigDecimal d = new BigDecimal(obj.toString());
				return d;
			}
		}catch(Exception e){
			return null;
		}
	}
	
	public static byte toByte(Object obj, Byte defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		try{
			int n = toInt(obj, defaultvalue);
			return (byte)n;
		}catch(Exception e){
			return defaultvalue;
		}
	} 
	
	public static Date toDate(Object obj, Date defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		if(obj instanceof Date){
			return (Date)obj;
		}
		try{
			java.sql.Timestamp sqlTimestamp = (java.sql.Timestamp)obj;
			//Date date = (Date)sqlTimestamp;
			return sqlTimestamp;
		}catch(Exception e){
			return defaultvalue;
		}
	}
	
	public static java.sql.Date toSqlDate(Object obj, java.sql.Date defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		try{
			java.sql.Timestamp sqlTimestamp = (java.sql.Timestamp)obj;
			java.sql.Date date = new java.sql.Date(sqlTimestamp.getTime());
			return date;
		}catch(Exception e){
			return defaultvalue;
		}
	}
	
	public static java.sql.Timestamp toSqlDateTime(Object obj, java.sql.Timestamp defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		try{
			java.sql.Timestamp sqlTimestamp = (java.sql.Timestamp)obj; 
			return sqlTimestamp;
		}catch(Exception e){
			return defaultvalue;
		}
	}
	
	public static boolean toBoolean(Object obj, boolean defaultvalue){
		if(obj == null) {
			return defaultvalue;
		}
		if(obj instanceof Boolean) {
			return (Boolean)obj;
		}
		boolean b = Boolean.valueOf(obj.toString());
		return b;
		
	}
	
	/**将字符串转为对象，如果是数字类型，则null的情况下返回其默认值0
	 * @param strValue 字符串
	 * @param objType 对象类型
	 * @param genericType 泛型类型（或者数组内的值的类型）
	 * @return
	 * @author: wanghua
	 */
	public static Object toObject(String strValue, Class<?> objType, Type genericType) throws JsonProcessingException {
		Object resultValue = null;
		String pvalue = strValue;
	 
		if (pvalue != null && pvalue.length() > 0) { // 值不为空
			if (objType.equals(String.class)) { // 参数类型为String
				if (!pvalue.startsWith("\"")) {
					resultValue = pvalue;
				} else {
					resultValue = TJSON.convertToObject(String.class, pvalue);
				}
			} else if (objType.equals(ArrayList.class)
					|| objType.equals(List.class)) { // 参数类型为List		 
				ParameterizedType pt = (ParameterizedType) genericType;
				Class<?> actType = (Class<?>) pt.getActualTypeArguments()[0];//获取ArrayList中存储的值的类型
				if(!pvalue.startsWith("[")) {
					pvalue = "[" + pvalue + "]";
				}
				Object value = TJSON.convertToList(actType, pvalue);
				resultValue = value;
			} else { // 普通java bean或者数组
				Object value = TJSON.convertToObject(objType, pvalue);
				resultValue = value;
			}
		}
	 
		if(resultValue == null){
			try {
				Class<?> paramType = objType;
				//int, double, float, long, short, boolean, byte, char
				if(paramType.equals(int.class) || paramType.equals(double.class)
						|| paramType.equals(float.class) || paramType.equals(long.class)
						|| paramType.equals(short.class) || paramType.equals(boolean.class)
						|| paramType.equals(byte.class) || paramType.equals(char.class)){
					resultValue = ReflectUtil.getDefaultValue(paramType);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return resultValue;
	}
	
	/**保留小数位数
	 * 
	 * @param value
	 * @param newScale 小数位数
	 * @return 
	 * @author: wanghua
	 */
	public static double round(double value, int newScale) {
		//BigDecimal d = new BigDecimal(value + 0.000000001); //加0.000000001 ，是为了避免 0.355 保留2位小数输出为  0.35 的情况，类似的数还有346.255 等
		
		//或者这样初始化,也可以避免 0.00499999999999这样的情况
		BigDecimal d = new BigDecimal(Double.toString(value));
		//d.setScale(newScale)
		double newValue = d.setScale(newScale, RoundingMode.HALF_UP).doubleValue();
		return newValue;
		
		/**
		 * Math.round 存在同样的问题
		 * Math.round(d*100) / 100;
		 * 4.015 保留两位小数 输出的是 4.01而不是4.02
		 */
	}
	
	/**保留小数位数
	 * 
	 * @param value
	 * @param newScale 小数位数
	 * @return 
	 * @author: wanghua
	 */
	public static double round(Double value, int newScale) {
		if(value == null)return 0;
		return round(value.doubleValue(), newScale);
	}
	/**将java对象转为map对象
	 * 
	 * @param bean
	 * @return
	 * @throws Exception 
	 * @author: wanghua
	 */
    public static Map<String, Object> convertToMap(Object bean) throws Exception { 
    	Map<String, Object> map = new HashMap<>();
        if (bean != null) {
            BeanMap beanMap = new BeanMap(bean);
            for (Entry<Object, Object> entrySet : beanMap.entrySet()) {
                map.put(entrySet.getKey().toString(), entrySet.getValue());
            }
        }
        return map;
    }
}
